package com.kenti.util;

import cn.hutool.core.net.URLEncodeUtil;
import cn.hutool.core.util.ZipUtil;
import com.alibaba.fastjson2.JSONObject;
import com.kenti.domain.IpPoolBean;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.File;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.lang.reflect.Field;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * 网络请求工具
 */
@Slf4j
public class HttpUtil {
    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    private static final MediaType XML = MediaType.parse("application/xml; charset=utf-8");
    private static final MediaType TEXT = MediaType.parse("text/plain; charset=utf-8");
    /**
     * 代理IP
     */
    public static final String P_PROXY_IP="proxyIp";
    /**
     * 响应内容类型
     * txt,byte
     */
    public static final String P_RESP_CONTENT_TYPE="resp_content_type";
    /**
     * 代理端口
     */
    public static final String P_PROXY_PORT="proxyPort";
    /**
     * 代理认证用户名
     */
    public static final String P_PROXY_USER="proxyUser";
    /**
     * 代理认证密码
     */
    public static final String P_PROXY_PASS="proxyPass";
    /**
     * 强制使用代理
        */
    public static final String P_FORCE_USE_PROXY="forceUseProxy";
    /**
     * 代理类型
     */
    public static final String P_PROXY_TYPE="proxyType";
    /**
     * 使用代理
     */
    public static final String P_USE_PROXY="useProxy";
    /**
     * 最后一个代理ip
     */
    public static final String P_LAST_PROXY_IP="lastProxyIp";
    /**
     * 最后一个代理端口
     */
    public static final String P_LAST_PROXY_PORT="lastProxyPort";
    /**
     * 是否302自动跳转
     */
    public static final String P_FOLLOW_REDIRECTS="followRedirects";
    /**
     * 重试次数
     */
    public static final String P_RETRY_COUNT="retry_count";
    /**
     * 显示请求详情
     */
    public static final String P_SHOW_REQUEST_DETAIL="showRequestDetail";
    /**
     * 超时时间（秒）
     */
    public static final String P_TIME_OUT="timeOut";
    public static final String P_FROM_IP="from_IP";
    public static final String P_FROM_SITE_TYPE="from_site_type";

    public static void fill(Map<String,String> header, IpPoolBean ipPoolBean){
        if (ipPoolBean.getType()==1){
            header.put(HttpUtil.P_PROXY_TYPE,"SOCKS");
        }
        header.put(HttpUtil.P_PROXY_IP,ipPoolBean.getIp());
        header.put(HttpUtil.P_PROXY_PORT,String.valueOf(ipPoolBean.getPort()));
        if (StringUtils.isNotBlank(ipPoolBean.getUserName())){
            header.put(HttpUtil.P_PROXY_USER,ipPoolBean.getUserName());
            header.put(HttpUtil.P_PROXY_PASS,ipPoolBean.getPassword());
        }
    }
    public static final List<String> notPutToHeader=new ArrayList<>();
    static {
        Field[] declaredFields = HttpUtil.class.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            String name = declaredField.getName();
            if (name.startsWith("P_")){
                Object o = null;
                try {
                    o = declaredField.get(null);
                    notPutToHeader.add(o+"");
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }

            }
        }
    }
    public static Function<Map<String,String>,IpPoolBean> getProxyIp;
    public static Consumer<Map<String,String>> processProxy;
    static ArrayList<String> RsponseHeaders = new ArrayList<>();
    private static OkHttpClient c;
    static {
        RsponseHeaders.add("Content-Type");
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.retryOnConnectionFailure(false)
                .connectTimeout(50, TimeUnit.SECONDS)
                .readTimeout(50, TimeUnit.SECONDS)
                .writeTimeout(50, TimeUnit.SECONDS)
                .callTimeout(50, TimeUnit.SECONDS)
                .hostnameVerifier((hostname, session) -> true);
        builder.sslSocketFactory(getSSLSocketFactory(),getTrustManager());
        c=builder.build();
        c.dispatcher().setMaxRequestsPerHost(10001111);
        c.dispatcher().setMaxRequests(10000111);
    }



    public static OkHttpClient getClient(Map<String,String> header){
        System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2,TLSv1.3");
        String followRedirects=header.get(P_FOLLOW_REDIRECTS);
        String proxyIp=header.get(P_PROXY_IP);
        String proxyPort=header.get(P_PROXY_PORT);
        String proxyUser=header.get(P_PROXY_USER);
        String proxyPass=header.get(P_PROXY_PASS);
        String proxyType=header.get(P_PROXY_TYPE);
        String useProxy=header.get(P_USE_PROXY);
        String forceUseProxy=header.get(P_FORCE_USE_PROXY);

        OkHttpClient.Builder builder = c.newBuilder()
                .protocols(Arrays.asList(Protocol.HTTP_1_1));
        if (StringUtils.isNotBlank(followRedirects)&& "false".equals(followRedirects)){
            builder.followRedirects(false);
        }
        Integer timeOut = MapUtils.getInteger(header, P_TIME_OUT, 50);
        builder.retryOnConnectionFailure(false)
                .connectTimeout(timeOut, TimeUnit.SECONDS)
                .readTimeout(timeOut, TimeUnit.SECONDS)
                .writeTimeout(timeOut, TimeUnit.SECONDS)
                .callTimeout(timeOut, TimeUnit.SECONDS);
        if (!"false".equals(useProxy) || "true".equalsIgnoreCase(forceUseProxy)) {
            if (StringUtils.isNotBlank(proxyIp)) {
                if (MapUtils.getBoolean(header,P_SHOW_REQUEST_DETAIL,true)) {
//                    log.info("使用代理请求网络,{},{}", proxyIp, proxyPort);
                }
                Proxy proxy = new Proxy("SOCKS".equalsIgnoreCase(proxyType) ? Proxy.Type.SOCKS : Proxy.Type.HTTP,
                        new InetSocketAddress(proxyIp, Integer.parseInt(proxyPort)));
                builder = builder.proxy(proxy);
                if (StringUtils.isNotBlank(proxyUser)) {
                    if (MapUtils.getBoolean(header,P_SHOW_REQUEST_DETAIL,true)) {
//                        log.info("使用代理授权,{},{}", proxyUser, proxyPass);
                    }
                    builder.proxyAuthenticator(new Authenticator() {
                        @Nullable
                        @Override
                        public Request authenticate(@Nullable Route route, @NotNull Response response) throws IOException {
                            String credential = Credentials.basic(proxyUser, proxyPass);
                            return response.request().newBuilder().header("Proxy-Authorization", credential)
                                    .build();
                        }
                    });
                }
            } else if (getProxyIp != null) {
                IpPoolBean ipPoolBean = getProxyIp.apply(header);
                if (ipPoolBean != null) {
                    Proxy.Type type = ipPoolBean.getType() == 0 ? Proxy.Type.HTTP : Proxy.Type.SOCKS;
                    header.put(P_LAST_PROXY_IP, ipPoolBean.getIp());
                    header.put(P_LAST_PROXY_PORT, String.valueOf(ipPoolBean.getPort()));
                    builder = builder.proxy(new Proxy(type, new InetSocketAddress(ipPoolBean.getIp(), ipPoolBean.getPort())));
                    if (StringUtils.isNotBlank(ipPoolBean.getUserName())) {
                        if (MapUtils.getBoolean(header,P_SHOW_REQUEST_DETAIL,true)) {
//                            log.info("使用代理授权,{},{},{},{}", ipPoolBean.getIp(), ipPoolBean.getPort(), ipPoolBean.getUserName(), ipPoolBean.getPassword());
                        }
                        builder.proxyAuthenticator(new Authenticator() {
                            @Nullable
                            @Override
                            public Request authenticate(@Nullable Route route, @NotNull Response response) throws IOException {
                                String credential = Credentials.basic(ipPoolBean.getUserName(), ipPoolBean.getPassword());
                                return response.request().newBuilder().header("Proxy-Authorization", credential)
                                        .build();
                            }
                        });
                    } else {
                        if (MapUtils.getBoolean(header,P_SHOW_REQUEST_DETAIL,true)) {
//                            log.info("使用代理请求网络,{},{}", ipPoolBean.getIp(), ipPoolBean.getPort());
                        }
                    }
                }else {
                    if ("true".equalsIgnoreCase(forceUseProxy)){
                        //没有代理
                        log.error("没有代理");
                        return null;
                    }
                }
            }else{
                if ("true".equalsIgnoreCase(forceUseProxy)){
                    //没有代理
                    log.error("没有代理");
                    return null;
                }
            }
        }
        OkHttpClient build = builder
                // 拦截器
//                .addInterceptor()
                .build();
        return build;
    }

    public static SSLSocketFactory getSSLSocketFactory() {
        try {
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, getTrustManager1(), new SecureRandom());
            return sslContext.getSocketFactory();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    private static TrustManager[] getTrustManager1() {
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(X509Certificate[] chain, String authType) {
                    }

                    @Override
                    public void checkServerTrusted(X509Certificate[] chain, String authType) {
                    }

                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[]{};
                    }
                }
        };
        return trustAllCerts;
    }
    private static X509TrustManager getTrustManager() {
        return new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[]{};
            }
        };
    }
    public static String upload(String url,String fileType,String fileName,Map<String,String> params,byte[] file,Map<String,String> headers) throws IOException {

        RequestBody fileBody = RequestBody.create(MediaType.parse(fileType), file);

        MultipartBody.Builder builder = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
///                .addPart(
//                        Headers.of("Content-Disposition", "form-data; name=\"file\"; filename=\"" + fileName + "\""),
//                        RequestBody.create(MEDIA_TYPE_PNG, file))
//                .addPart(
//                        Headers.of("Content-Disposition", "form-data; name=\"imagetype\""),
//                        RequestBody.create(null, imageType))
//                .addPart(
//                        Headers.of("Content-Disposition", "form-data; name=\"userphone\""),
//                        RequestBody.create(null, userPhone))

                .addFormDataPart("file", fileName, fileBody);
        for (String s : params.keySet()) {
            builder.addFormDataPart(s, params.get(s));
        }
        RequestBody requestBody = builder.build();
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        execute(request,headers);
        return null;
    }

    /**
     * 下载文件
     * @param fileName
     * @param url
     * @throws IOException
     */
    public static boolean downloadFile(String fileName,String url,Map<String,String> headers) throws IOException {
        File file = new File(fileName);
        Request.Builder builder = new Request.Builder();
        addHeader(headers,builder);
        Request request = builder.url(url).build();
        log.info("download url:{}",url);
        HttpResponse response=download(file,request,headers);
        return response.isSuccess();
    }

    /**
     * get 请求
     * @param url       请求url地址
     * @return string
     * */
    public static HttpResponse doGet(String url)throws IOException {
        return doGet(url, null,new HashMap<>());
    }


    /**
     * get 请求
     * @param url       请求url地址
     * @param params    请求参数 map
     * @return string
     * */
    public static HttpResponse doGet(String url, Map<String, String> params)throws IOException {
        return doGet(url, params,new HashMap<>());
    }

    /**
     * get 请求
     * @param url       请求url地址
     * @param headers   请求头字段 {k1, v1 k2, v2, ...}
     * @return string
     * */
    public static HttpResponse doGet(String url, String... headers)throws IOException {
        return doGet(url, null, headers);
    }

    private static void addHeader(Map<String, String> headers, Request.Builder builder) {
        if (headers !=null && headers.size()>0){
            headers.forEach((k, v)->{
                if (!notPutToHeader.contains(k)){
                    try {
                        if (StringUtils.isNotBlank(k) && StringUtils.isNotBlank(v)){
                            builder.addHeader(k,v);
                        }
                    }catch (Exception e){
                        //cookie值错误
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    public static HttpResponse doGet(String url, Map<String, String> params, Map<String, String> headers) throws IOException{
        StringBuilder sb = new StringBuilder(url);
        if (params != null && params.keySet().size() > 0) {
            boolean firstFlag = !url.contains("?");
            for (String key : params.keySet()) {
                if (firstFlag) {
                    sb.append("?").append(key).append("=").append(URLEncodeUtil.encodeAll(params.get(key)));
                    firstFlag = false;
                } else {
                    sb.append("&").append(key).append("=").append(URLEncodeUtil.encodeAll(params.get(key)));
                }
            }
        }

        Request.Builder builder = new Request.Builder();
        addHeader(headers,builder);
        Request request = builder.url(sb.toString()).build();
        if (MapUtils.getBoolean(headers,P_SHOW_REQUEST_DETAIL,true)){
            log.info("do get request and url[{}]", sb.toString());
        }
        return execute(request,headers);
    }

    public static HttpResponse doPostText(String url, String json,Map<String,String> header) throws IOException {
        if (MapUtils.getBoolean(header,P_SHOW_REQUEST_DETAIL,false)) {
            log.info("do post request and url[{}]", url);
        }
        return exectePost(url, json,header);
    }

    private static HttpResponse exectePost(String url, String data,Map<String,String> header) throws IOException {
        RequestBody requestBody = RequestBody.create(TEXT,data);
        Request.Builder builder = new Request.Builder();
        addHeader(header,builder);
        Request request = builder.url(url).post(requestBody).build();
        return execute(request,header);
    }

    /**
     * get 请求
     * @param url       请求url地址
     * @param params    请求参数 map
     * @param headers   请求头字段 {k1, v1 k2, v2, ...}
     * @return string
     * */
    public static HttpResponse doGet(String url, Map<String, String> params, String[] headers) throws IOException{


        Map<String, String> headerMap=new HashMap<>();
        if (headers != null && headers.length > 0) {
            if (headers.length % 2 == 0) {
                for (int i = 0; i < headers.length; i = i + 2) {
                    headerMap.put(headers[i], headers[i + 1]);
                }
            } else {
                log.warn("headers's length[{}] is error.", headers.length);
            }
        }
        return doGet(url,params,headerMap);
    }

    /**
     * post 请求
     * @param url       请求url地址
     * @param params    请求参数 map
     * @return string
     */
    public static HttpResponse doPost(String url, Map<String, String> params) throws IOException {
        FormBody.Builder builder = new FormBody.Builder();

        if (params != null && params.keySet().size() > 0) {
            for (String key : params.keySet()) {
                builder.add(key, params.get(key));
            }
        }
        Request request = new Request.Builder().url(url).post(builder.build()).build();
        log.info("do post request and url[{}]", url);
        return execute(request, new HashMap<>());
    }

    /**
     * post 请求
     * @param url       请求url地址
     * @param params    请求参数 map
     * @return string
     */
    public static HttpResponse doPost(String url, Map<String, String> params,String... headers) throws IOException {
        FormBody.Builder builder = new FormBody.Builder();

        if (params != null && params.keySet().size() > 0) {
            for (String key : params.keySet()) {
                builder.add(key, params.get(key));
            }
        }

        Request.Builder rbuilder = new Request.Builder().url(url).post(builder.build());
        Map<String, String> headerMap=new HashMap<>();
        if (headers != null && headers.length > 0) {
            if (headers.length % 2 == 0) {
                for (int i = 0; i < headers.length; i = i + 2) {
                    headerMap.put(headers[i], headers[i + 1]);
                }
                addHeader(headerMap,rbuilder);
            } else {
                log.warn("headers's length[{}] is error.", headers.length);
            }
        }
        if (MapUtils.getBoolean(headerMap,P_SHOW_REQUEST_DETAIL,true)) {
            log.info("do post request and url[{}]", url);
        }
        return execute(rbuilder.build(),headerMap);
    }

    public static HttpResponse doPost(String url, JSONObject params,Map<String, String> headers) throws IOException {
        FormBody.Builder builder = new FormBody.Builder();

        if (params != null && params.keySet().size() > 0) {
            for (String key : params.keySet()) {
                builder.add(key, params.getString(key));
            }
        }
        Request.Builder rbuilder = new Request.Builder().url(url).post(builder.build());
        addHeader(headers,rbuilder);
        if (MapUtils.getBoolean(headers,P_SHOW_REQUEST_DETAIL,true)) {
            log.info("do post request and url[{}]", url);
        }
        return execute(rbuilder.build(),headers);
    }
    public static HttpResponse doPost(String url, Map<String, String> params,Map<String, String> headers) throws IOException {
        FormBody.Builder builder = new FormBody.Builder();
        if (params != null && params.keySet().size() > 0) {
            for (String key : params.keySet()) {
                builder.add(key, params.get(key));
            }
        }
        Request.Builder rbuilder = new Request.Builder().url(url).post(builder.build());
        addHeader(headers,rbuilder);
        if (MapUtils.getBoolean(headers,P_SHOW_REQUEST_DETAIL,true)) {
            log.info("do post request and url[{}]", url);
        }
        return execute(rbuilder.build(),headers);
    }

    public static HttpResponse doPut(String url, Map<String, String> params,Map<String, String> headers) throws IOException {
        FormBody.Builder builder = new FormBody.Builder();
        if (params != null && params.keySet().size() > 0) {
            for (String key : params.keySet()) {
                builder.add(key, params.get(key));
            }
        }
        Request.Builder rbuilder = new Request.Builder().url(url).put(builder.build());
        addHeader(headers,rbuilder);
        if (MapUtils.getBoolean(headers,P_SHOW_REQUEST_DETAIL,true)) {
            log.info("do put request and url[{}]", url);
        }
        return execute(rbuilder.build(),headers);
    }

    public static HttpResponse doPutJson(String url,String json,Map<String, String> headers) throws IOException {
        RequestBody requestBody = RequestBody.create(JSON, json);
        Request.Builder rbuilder = new Request.Builder().url(url).put(requestBody);
        addHeader(headers,rbuilder);
        if (MapUtils.getBoolean(headers,P_SHOW_REQUEST_DETAIL,true)) {
            log.info("do put request and url[{}]", url);
        }
        return execute(rbuilder.build(),headers);
    }public static HttpResponse doPatchJson(String url,String json,Map<String, String> headers) throws IOException {
        RequestBody requestBody = RequestBody.create(JSON, json);
        Request.Builder rbuilder = new Request.Builder().url(url).patch(requestBody);
        addHeader(headers,rbuilder);
        if (MapUtils.getBoolean(headers,P_SHOW_REQUEST_DETAIL,true)) {
            log.info("do put request and url[{}]", url);
        }
        return execute(rbuilder.build(),headers);
    }

    public static HttpResponse doDeleteJson(String url,String json,Map<String, String> headers) throws IOException {
        RequestBody requestBody = RequestBody.create(JSON, json);
        Request.Builder rbuilder = new Request.Builder().url(url).delete(requestBody);
        addHeader(headers,rbuilder);
        if (MapUtils.getBoolean(headers,P_SHOW_REQUEST_DETAIL,false)) {
            log.info("do delete request and url[{}]", url);
        }
        return execute(rbuilder.build(),headers);
    }
    public static HttpResponse doDelete(String url,Map<String, String> params,Map<String, String> headers) throws IOException {
        FormBody.Builder builder = new FormBody.Builder();
        if (params != null && params.keySet().size() > 0) {
            for (String key : params.keySet()) {
                builder.add(key, params.get(key));
            }
        }
        Request.Builder rbuilder = new Request.Builder().url(url).delete(builder.build());
        addHeader(headers,rbuilder);
        if (MapUtils.getBoolean(headers,P_SHOW_REQUEST_DETAIL,false)) {
            log.info("do delete request and url[{}]", url);
        }
        return execute(rbuilder.build(),headers);
    }


    /**
     * post 请求, 请求数据为 json 的字符串
     * @param url       请求url地址
     * @param json      请求数据, json 字符串
     * @return string
     */
    public static HttpResponse doPostJson(String url, String json) throws IOException {
        log.info("do post request and url[{}]", url);
        return exectePost(url, json, JSON);
    }
    public static HttpResponse doPostJson(String url, String json,Map<String,String> header) throws IOException {
        if (MapUtils.getBoolean(header,P_SHOW_REQUEST_DETAIL,true)) {
            log.info("do post request and url[{}]", url);
        }
        return exectePost(url, json, JSON,header);
    }

    /**
     * post 请求, 请求数据为 xml 的字符串
     * @param url       请求url地址
     * @param xml       请求数据, xml 字符串
     * @return string
     */
    public static HttpResponse doPostXml(String url, String xml) throws IOException {
        return exectePost(url, xml, XML);
    }

    private static HttpResponse exectePost(String url, String data, MediaType contentType,Map<String,String> header) throws IOException {
        RequestBody requestBody = RequestBody.create(contentType, data);
        Request.Builder builder = new Request.Builder();
        addHeader(header,builder);
        Request request = builder.url(url).post(requestBody).build();
        return execute(request,header);
    }

    private static HttpResponse exectePost(String url, String data, MediaType contentType) throws IOException {
        RequestBody requestBody = RequestBody.create(contentType, data);
        Request request = new Request.Builder().url(url).post(requestBody).build();
        return execute(request,new HashMap<>());
    }

    private static HttpResponse download(File file, Request request,Map<String,String> headers) throws IOException {
        Response response = null;
        HttpResponse r=new HttpResponse();
        String retry = headers.get(P_RETRY_COUNT);
        int count=(StringUtils.isNotBlank(retry))?0:Integer.parseInt(retry);
        while (count<5){
            try {
                response = getClient(headers).newCall(request).execute();
                if (response.isSuccessful()) {
                    FileUtils.copyInputStreamToFile(response.body().byteStream(), file);
                }else{
                    r.setSuccess(false);
                    r.setMessage(response.code()+response.message());
                }
                return r;
            }catch (Exception e){
                if(e instanceof InterruptedIOException){
                    throw e;
                }
                count++;
                log.error("网络请求失败 正在重试--第{}次",count);
            } finally {
                if (response != null) {
                    response.close();
                }
            }
        }
        r.setSuccess(false);
        r.setMessage("网络请求出错");
        return r;
    }

    private static HttpResponse execute(Request request,Map<String, String> headerMap) throws IOException {
        Response response = null;
        HttpResponse r = new HttpResponse();
        String retry = headerMap.get(P_RETRY_COUNT);
        String respContentType = headerMap.get(P_RESP_CONTENT_TYPE);
        Integer counts=4;
        if(StringUtils.isNotBlank(retry)){
            counts=Integer.valueOf(retry);
        }
        Integer count=0;
        StringBuffer errors=new StringBuffer();
        while (count <= counts) {
            try {
                response = getClient(headerMap).newCall(request).execute();
                r.setCode(response.code());
                String contentType = response.header("content-type");
                if (StringUtils.isNotBlank(contentType)){
                    r.getExternal().put("content-type", contentType);
                }
                List<String> headers = response.headers("Set-Cookie");
                StringBuffer clearCookie = new StringBuffer();
                MediaType mediaType = response.body().contentType();
                r.setMediaType(mediaType);
                if (headers != null && headers.size() > 0) {
                    JSONObject cookies = new JSONObject();
                    for (int i = 0; i < headers.size(); i++) {
                        String s = headers.get(i);
                        try {
                            String str = s.split(";")[0];
                            String key = str.substring(0, str.indexOf("="));
                            String value = str.substring(str.indexOf(key + "=")+(key + "=").length());
                            cookies.put(key, value);
                            clearCookie.append(key + "=" + value);
                            if (i<headers.size()-1){
                                clearCookie.append(";");
                            }
                        } catch (Exception e) {
                            log.error("处理返回cookie失败",e);
                        }
                    }
                    r.getExternal().put("cookieSplit", cookies);
                    r.getExternal().put("cookies", clearCookie.toString());
                }
                for (String header : RsponseHeaders) {
                    String cs = response.headers().get(header);
                    if (StringUtils.isNotBlank(cs)) {
                        r.getExternal().put(header, cs);
                    }
                }

                if (response.isSuccessful()) {
                    r.getExternal().put("location", response.request().url().toString());
                    if ("byte".equalsIgnoreCase(respContentType)){
                        byte[] bytes = response.body().bytes();
                        try {
                            r.setBytes(ZipUtil.unGzip(bytes));
                        }catch (Exception e){
                            r.setBytes(bytes);
                        }
                    }else if ("text".equalsIgnoreCase(respContentType)){
                        r.setResponse(response.body().string());
                    }else{
                        if (mediaType != null) {
                            if (mediaType.toString().contains("image")
                                    || mediaType.toString().contains("video")
                                    || mediaType.toString().contains("audio")) {
                                r.setBytes(response.body().bytes());
                            } else {
                                r.setResponse(response.body().string());
                            }
                        } else {
                            r.setResponse(response.body().string());
                        }
                    }
                } else {
                    r.setSuccess(false);
                    if (response.code() == 302 || response.code() == 301) {
                        r.getExternal().put("location", response.header("location"));
                    }
                    r.setResponse(response.body().string());
                    r.setMessage(response.code() + response.message());
                }

                return r;
            } catch (Exception e) {
                count++;
                errors.append(e.getMessage()+"\n");
                log.error("网络请求失败 正在重试--第{}次,{}", count,errors);
                if (processProxy!=null){
                    processProxy.accept(headerMap);
                }
            } finally {
                if (response != null) {
                    response.close();
                }
            }
        }
        r.getExternal().put("url", request.url().toString());
        r.setCode(0);
        r.setSuccess(false);
        r.setMessage(errors.toString());
        r.setResponse(errors.toString());
        return r;
    }
    @Data
    public static class HttpResponse{
        private boolean success=true;
        private Integer code;
        private String response;
        private MediaType mediaType;
        private byte[] bytes;
        private String message;
        private JSONObject external=new JSONObject();

        private JSONObject cacheSetting;
        public void setMessage(String message) {
            this.message = message;
            this.success=false;
        }
    }

}
